﻿using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web.Mvc;
using System.Xml.Serialization;
using ABC.XPath;
using ABC.XPath.NodePolicy;

namespace ABC.Mvc
{
	[XmlRoot( "Value" )]
	public class Pair
	{
		[XmlAttribute]
		public string Key { get; set; }

		[Transparent( true )]
		public object Value { get; set; }
	}

	public class ViewDataNodePolicy : CollectionNodePolicyBase
	{
		private List<string> _children;
		private Regex _regex = new Regex( "^[A-Z][A-Z0-9._-]*$", RegexOptions.IgnoreCase );

		/// <summary>
		/// Gets the node policy object.
		/// </summary>
		/// <returns>Returns an instance of this node policy.</returns>
		public static new INodePolicy GetPolicy()
		{
			return new ViewDataNodePolicy();
		}

		/// <summary>
		/// Creates a new <see cref="ABC.Dictionary.Util.DictionaryNodePolicy"/> instance.
		/// </summary>
		protected ViewDataNodePolicy() { }

		/// <summary>
		/// See <see cref="INodePolicy.GetAttributesCount"/> for details.
		/// </summary>
		public override int GetAttributesCount( Node node )
		{
			return 0;
		}

		private void PrepareChildren( IDictionary<string, object> dic )
		{
			if( _children == null )
				_children = dic.Keys.ToList();
		}

		/// <summary>
		/// See <see cref="INodePolicy.GetName"/> for details.
		/// </summary>
		public override string GetName( Node node )
		{
			return "ViewData";
		}

		/// <summary>
		/// See <see cref="INodePolicy.GetChildrenCount"/> for details.
		/// </summary>
		public override int GetChildrenCount( Node node )
		{
			var viewDataDic = (ViewDataDictionary)node.Object;
			return viewDataDic.Count + 1;
		}

		/// <summary>
		/// See <see cref="INodePolicy.GetChild"/> for details.
		/// </summary>
		public override Node GetChild( Node node, int index )
		{
			var viewDataDic = (ViewDataDictionary) node.Object;
			PrepareChildren( viewDataDic );

			if( index >= 0 && index < viewDataDic.Count )
			{
				if( _regex.Match( _children[index] ).Success )
				{
					var childNode = CreateChildNode( viewDataDic[_children[index]], node );
					childNode.Name = _children[index];
					return childNode;
				}
				return CreateChildNode( new Pair { Key = _children[index], Value = viewDataDic[_children[index]] }, node );
			}
			if( index == viewDataDic.Count && viewDataDic.Model != null )
				return new Node( node.Context, node.Context.GetNodePolicy( viewDataDic.Model ) )
				       	{ Object = viewDataDic.Model, Name = "Model" };

			return null;
		}
	}
}
